构建优化基础

影响构建速度的因素

主要有以下几个方面:

构建耗时分析工具

Build Analyzer

Build Analyzer,是 Android Studio 提供的构建分析器,可以在 build 窗口中打开查看。

--profile

Profile 是 Gradle 提供的构建检测工具,通过命令行执行 --profile 可以在本地生产一份 HTML 报告。

./gradlew assembleDebug --profile

在构建完成后,在 project-root/build/reports/profile/ 目录会生成构建报告。

如何查看?

Summary

默认是概览界面,包括 Total Build TimeConfiguring ProjectsTask Execution 等基本信息。

image.png|900

Configuration

Configuration 就是配置阶段耗时,包括 All projects、app 以及其它模块的配置时间。

Dependency Resolution

依赖解析耗时。

Artifact Transforms

Gradle 在新版本报告中还加入了 Transform 耗时,比如做些产物转换啊啥的

Task Execution

各个 Task 的执行时长。

image.png|800

Total Build Time 才 3s 呢,这个 Task Execution 怎么就 4s 了?

这是因为这里统计的是 Task 执行的总时长,实际编译过程中 Task 是 并行 在跑的,所以会出现大于总时长的情况。

--scan

scan 介绍

Build Scan 也是 Gradle 提供的构建分析工具,相比于 Profile 方式,Build Scan 提供的信息更加丰富,且是在线报告,而且还可以用来排查编译错误。

构建扫描(build scan)是一个中心化并且可以共享的构建记录,构建完成后会将报告发到:Getting started with Build Scan® for Gradle, Apache Maven™, and sbt | Gradle Inc.

使用 scan

命令

使用非常简单,命令加上 --scan 即可:

./gradlew build --scan
# 如果你是首次构建,报告上传Gradle服务器需要同意相关条款,yes即可
# 执行完毕,会随机生成一个链接
# 如果你是首次使用Build Scan,还需要输入邮箱激活一下

为项目默认添加 scan

除了每次在命令行中输入 --scan 以外, 还可以在项目中配置默认开启 scan. 需要在 Root Build Script(根项目目录下 build.gradle.kts ) 中加入:

// Root Build Script
plugins {
    `build-scan`
}
buildScan {
    publishAlways()
    termsOfServiceUrl = "https://gradle.com/terms-of-service"
    termsOfServiceAgree = "yes"
}

buildScan 是 BuildScanExtension 类型的 extension:

为所有项目添加 scan

还可以把 scan 的设置放在 Init Script(init.gradle.kts) 中, 这样既不改动项目的脚本, 又能为所有项目开启 scan, 这在 CI 上尤为实用

查看 scan 报告

Summary

这个概览信息就比 Profile 详细多了,其中包括你的 Gradle 版本total build timeprojects构建配置的开关编译的环境 等等。

image.png|800

Performance

Performance 的二级菜单要比 Profile 更丰富一些,除了 Build、Configuration、Dependency resolution、Task execution 这四项外,还有 Build Cache、Daemon、Network activity。

Task execution

这里除了展示所有 Task 的执行时间之外,还展示了有多少个 Task 是命中缓存的,有多少个 Task 是增量编译的等等。

image.png|800

Timeline

image.png|800

Timeline 里我们可以看到所有 Task 执行的时间线。

点击具体的 Task 可以看到执行的具体信息,点击「Focus on task in timeline」可以看到该 Task 在整个时间线的具体位置。

Switches

image.png|800

switches 里面会展示一些 Gradle 配置的开关状态,可以很好的帮助你查漏补缺。

比如我这里 Cache 都没开,并行编译也没开,离线也没开,如果这些都开了,构建性能又会有大大的提升。

gradle-doctor 三方插件发现构建慢问题

Gradle-doctor 插件 (构建时后输出可能导致构建慢的点)

https://runningcode.github.io/gradle-doctor
构建过程中,发现构建速度慢的,会打印 log 出来
image.png|900

Gradle 生命周期统计

Gradle 生命周期 hook 统计各个阶段耗时情况

构建优化思路?

  1. Gradle configuration 耗时?
  2. Kapt 耗时大户,迁移 ksp?
  3. Transform 优化
  4. Jetifier 移除?
  5. 升级到最新编译工具链 (Gradle 和 AGP 7. X 提升很大)

单仓还是多仓

多仓

优点

存在的问题

大仓 MonoRepo

什么是 MonoRepo?

将所有代码放在一个 Git 仓库中,通过分层来划分不同业务

MonoRepo 的缺点

相比较于分仓模式,MonoRepo 的编译速度会更慢,同步的时间也会更长。因为每个工程都需要重新 Configuration 策略,将 aar 依赖方式切换成源代码依赖。同时不同于 aar 依赖的情况,源代码依赖的情况下每个工程的 build.gradle 还有全局配置以及插件等都需要被执行到,所以消耗的时间会更长一点点。也就是正常的 gradle 相关的生命周期,对于源码编译的工程都是需要执行一次的

MonoRepo 优点

Ref